#include <iostream>
#include <iomanip>
#include <vector>
#include <string>
#include <cmath>

using namespace std;

typedef long long ll;

const int N = 2000;
const int M = 100000;
int tin[N];
int fup[N];

struct edge{
	int to;
	int id;
	edge() {}
	edge(int to, int id): to(to), id(id) {}
};

vector<edge> g[N];
int used[N];
int curused = 1;
bool isbr[M];

int br;
inline void dfs(int v, int p = -1, int curt = 0){
	used[v] = curused;
	tin[v] = fup[v] = curt;
	for (int i = 0; i < g[v].size(); ++i){
		int to = g[v][i].to;
		int id = g[v][i].id;
		if (id != p && used[to] != curused){
			dfs(to, id, curt + 1);
		}
		if (id != p && fup[to] < fup[v])
			fup[v] = fup[to];
	}
	if (p >= 0 && fup[v] == tin[v]){
		++br;
		isbr[p] = true;
	}
}

int cantuse;
inline void dfs1(int v, int p = -1, int curt = 0){
	used[v] = curused;
	tin[v] = fup[v] = curt;
	for (int i = 0; i < g[v].size(); ++i){
		int to = g[v][i].to;
		int id = g[v][i].id;
		if (id != p && used[to] != curused && id != cantuse){
			dfs1(to, id, curt + 1);
		}
		if (id != p && fup[to] < fup[v] && id != cantuse)
			fup[v] = fup[to];
	}
	if (p >= 0 && fup[v] == tin[v] && !isbr[p]){
		++br;
	}
}

int main(){
	ios_base::sync_with_stdio(false);
	int n, m; cin >> n >> m;
	for (int i = 0; i < m; ++i){
		int a, b;
		cin >> a >> b;
		--a; --b;
		g[a].push_back(edge(b, i));
		g[b].push_back(edge(a, i));
	}
	ll ans = 0;
	br = 0;
	dfs(0);
	ans += 1LL * br * (br - 1) / 2;
	ans += 1ll * br * (m - br);
	for (int i = 0; i < m; ++i) if (!isbr[i]){
		isbr[i] = true;
		br = 0;
		cantuse = i;
		++curused;
		dfs1(0);
		ans += br;
	}
	cout << ans << endl;
	return 0;
}